// SecurityAuthSystem.ts
import { _decorator, Component, Node, find, sys, EditBox, EventTouch, log, error, UIOpacity, Label, Tween, tween, director, JsonAsset, ResolutionPolicy, } from 'cc';
import Banner from '../Scripts/Tools/Banner';
import { GameData } from '../Scripts/Data/GameData';
const { ccclass, property } = _decorator;

// const appcode: string = "1c1e90296e36432f88a7fc64476b9587";//北京
// const appcode: string = "1cae0ad7e29d471c9d6dfd79914800ea";//自己的
const KEY_Authentication = "Authentication"//实名认证
const KEY_Firse = "KEY_Firse"//第一次登录

//test1
// const HOST = 'https://sxidcheck.market.alicloudapi.com';
// const PATH = '/idcard/check';

//test2 https://idenauthen.market.alicloudapi.com/idenAuthentication
// const HOST = 'https://idenauthen.market.alicloudapi.com';
// const PATH = '/idenAuthentication';

//test3 https://kzidcardv1.market.alicloudapi.com/api-mall/api/id_card/check
const HOST = ' https://kzidcardv1.market.alicloudapi.com';
const PATH = '/api-mall/api/id_card/check';
const METHOD = 'POST';
const APPCODE = '1cae0ad7e29d471c9d6dfd79914800ea'; // 替换真实AppCode

// const SQL_HOST = `http://localhost:3000`
const SQL_HOST = `http://47.111.102.176:3000`

enum USER_TYPE {
    高级,
    中级,
    初级,
    空白账号,
}

enum PLAYER {
    // 未满12周岁,
    未满8周岁,
    未成年,//12-18岁
    成年,
}

enum ERROR {
    名字错误 = "名字需要在2-10之内",
    身份证格式错误 = "身份证格式错误",//12-18岁
    响应数据解析失败 = "响应数据解析失败",
    网络请求异常 = "网络请求异常",
    请求超时 = "请求超时",
    认证失败 = "认证失败",
    结果不一致 = "输入身份证与名字不匹配",
}


//12-18岁玩家允许在选时间
const PlayingTime1: number = 120;//允许在线的时间
const PlayingTime2: number = 0;

interface _UserData {
    // age: number,//年龄
    birthday: string,//生日
    // lastLoginTime: string,//上次登录时间
    // playingTime: number,//允许在线时间
    name: string,//账号
    id: string,//密码
    isAuthentication: boolean,//是否已经实名认证
    isFirst: boolean,//是否是第一次进入游戏
    unlock: number,
}

const tableName: string = `yytm_data`;

@ccclass('Login')
export class Login extends Component {
    public static Instance: Login = null;

    @property
    NeedLogin: boolean = false;

    public Type: USER_TYPE = USER_TYPE.空白账号;
    public UserData: _UserData = null;
    public UserName: string = "";
    public Birthday: string = "";

    private _loginPanel: Node = null;
    private _loginName: EditBox = null;
    private _loginID: EditBox = null;
    private _loginTipsUIOpacity: UIOpacity = null;
    private _loginTipsLabel: Label = null;

    private _registerPanel: Node = null;
    private _registerName: EditBox = null;
    private _registerID: EditBox = null;
    private _registerTipsUIOpacity: UIOpacity = null;
    private _registerTipsLabel: Label = null;

    private _authenticationPanel: Node = null;
    private _EditBoxName: EditBox = null;
    private _EditBoxID: EditBox = null;

    private _under12YearOldPanel: Node = null;//未满12周岁界面
    private _under18YearOldPanel: Node = null;//12-18岁界面
    private _adultPanel: Node = null;//成年人登录提示界面
    private _timeOverPanel: Node = null;//游戏时间结束界面

    private _tipsUIOpacity: UIOpacity = null;
    private _tipsLabel: Label = null;

    private _rightAgePanel: Node = null;

    private _buttonBreak: Node = null;
    private _buttonStart: Node = null;

    private _isClick: boolean = true;//能都点击
    private _intervalId = null;//定时器

    private _targetPanel: Node = null;

    private _seniorUser: _UserData[] = [];//高级用户
    private _intermediateUser: _UserData[] = [];//中级用户
    private _naiveUser: _UserData[] = [];//初级用户
    private _nullUser: _UserData[] = [];//空白用户
    private _isFirst: boolean = false;

    onLoad() {
        Login.Instance = this;

        this._loginPanel = find("登录", this.node);
        this._loginName = find("登录/Panel/InputName/EditBox", this.node).getComponent(EditBox);
        this._loginID = find("登录/Panel/InputID/EditBox", this.node).getComponent(EditBox);
        this._loginTipsUIOpacity = find("登录/Panel/Tips", this.node).getComponent(UIOpacity);
        this._loginTipsLabel = find("登录/Panel/Tips/Tips", this.node).getComponent(Label);

        this._registerPanel = find("注册", this.node);
        this._registerName = find("注册/Panel/InputName/EditBox", this.node).getComponent(EditBox);
        this._registerID = find("注册/Panel/InputID/EditBox", this.node).getComponent(EditBox);
        this._registerTipsUIOpacity = find("注册/Panel/Tips", this.node).getComponent(UIOpacity);
        this._registerTipsLabel = find("注册/Panel/Tips/Tips", this.node).getComponent(Label);

        this._authenticationPanel = find("实名认证", this.node);
        this._EditBoxName = find("实名认证/Panel/InputName/EditBox", this.node).getComponent(EditBox);
        this._EditBoxID = find("实名认证/Panel/InputID/EditBox", this.node).getComponent(EditBox);
        this._tipsLabel = find("实名认证/Panel/Tips/Tips", this.node).getComponent(Label);
        this._tipsUIOpacity = find("实名认证/Panel/Tips", this.node).getComponent(UIOpacity);

        this._under12YearOldPanel = find("未满12周岁", this.node);
        this._under18YearOldPanel = find("未满18周岁", this.node);
        this._adultPanel = find("成年人登录提醒", this.node);
        this._timeOverPanel = find("游戏时间结束", this.node);

        this._rightAgePanel = find("适龄提示", this.node);
        this._buttonBreak = find("未满18周岁/Panel//Button/退出登录", this.node);
        this._buttonStart = find("未满18周岁/Panel//Button/开始游戏", this.node);
    }

    /**不需要账号登录 */
    // init() {

    //     // this.test();

    //     this._userData = this.getData();
    //     if (this._userData) {
    //         //已近实名认证过了---获取年龄跟生日

    //         //判断玩家类别
    //         const player: PLAYER = this.checkAgeByBirthday(this._userData.birthday);
    //         if (player == PLAYER.未满12周岁) {
    //             //退出登录
    //             this.showPanel(this._under12YearOldPanel);
    //         } else if (player == PLAYER.未成年) {
    //             //判断日期是否刷新--并且玩家是在12-18周岁之间
    //             // if (this.checkRefesh(this._userData.lastLoginTime)) {
    //             //     //刷新之后重置玩家的允许在线时间
    //             //     this.refesh();
    //             // }
    //             //进入游戏的同时也需要检测玩家在线时间
    //             // if (this._userData.playingTime <= 0) {
    //             //     //游戏时间已经完了
    //             //     this.showPanel(this._timeOverPanel);
    //             //     return;
    //             // }

    //             //是否是游戏时间
    //             const isGameTime = this.isAllowedTime();
    //             if (isGameTime) {
    //                 this._buttonStart.active = true;
    //                 this._buttonBreak.active = false;
    //                 // 设置间隔定时器（每1秒执行）
    //                 this._intervalId = setInterval(() => {
    //                     this.refeshTime();
    //                 }, 1000);
    //             } else {
    //                 this._buttonStart.active = false;
    //                 this._buttonBreak.active = true;
    //             }
    //             this.showPanel(this._under18YearOldPanel);
    //         } else if (player == PLAYER.成年) {
    //             this.startGame();
    //         }

    //     } else {
    //         //进行实名认证
    //         this.showPanel(this._authenticationPanel);
    //     }
    // }

    /**需要账号登录 */
    async init() {
        if (this.NeedLogin && this.UserName === "") {
            this.showPanel(this._loginPanel);
            return;
        }

        try {
            const results = await this.getDataByName(this.UserName);
            if (results.found) {
                //已近实名认证过了---获取年龄跟生日

                const player: PLAYER = this.checkAgeByBirthday(this.Birthday);
                if (player == PLAYER.未满8周岁) {
                    //退出登录
                    this.showPanel(this._under12YearOldPanel);
                } else if (player == PLAYER.未成年) {
                    //是否是游戏时间
                    const isGameTime = this.isAllowedTime();
                    if (isGameTime) {
                        this._buttonStart.active = true;
                        this._buttonBreak.active = false;
                        // 设置间隔定时器（每1秒执行）
                        this._intervalId = setInterval(() => {
                            this.refeshTime();
                        }, 1000);
                    } else {
                        this._buttonStart.active = false;
                        this._buttonBreak.active = true;
                    }
                    this.showPanel(this._under18YearOldPanel);
                } else if (player == PLAYER.成年) {
                    this.showPanel(this._adultPanel);
                }
            } else {
                this.showPanel(this._authenticationPanel);
            }
        } catch (e) {
            console.log(e.message);
        }
    }

    startGame() {
        this.closePabel();
        director.loadScene("MainScene");
        // director.loadScene(GameManager.StartScene);
        //加载场景
    }

    /**展示界面 */
    showPanel(panel: Node) {
        if (this._targetPanel == panel) return;
        if (this._targetPanel) this._targetPanel.active = false;
        this._targetPanel = panel;
        this._targetPanel.active = true;
    }

    /**关闭界面 */
    closePabel() {
        if (this._targetPanel) {
            this._targetPanel.active = false;
            this._targetPanel = null;
        }
    }

    /**展示适龄提示 */
    showRightAgePanel() {
        this.showPanel(this._rightAgePanel);
    }

    /**展示适龄提示 */
    onButtonClick(event: EventTouch) {
        const target: Node = event.getCurrentTarget();

        switch (target.name) {
            case "开始认证":
                if (!this._isClick) return;
                this._isClick = false;
                this._isFirst = true;
                this.startRZ(this._EditBoxName.string, this._EditBoxID.string);
                break;
            case "退出适龄提示":
                this.closePabel();
                break;
            case "开始游戏":
                this.startGame();
                break;
            case "退出登录":
                Banner.Instance.Quit();
                break;
            case "登录":
                this.login(this._loginName.string, this._loginID.string);
                break;
            case "注册":
                this.register(this._registerName.string, this._registerID.string);
                break;
            case "点击注册":
                this.showPanel(this._registerPanel);
                break;
            case "退出注册":
                this.showPanel(this._loginPanel);
                break;
        }

    }

    /**登录 */
    login(username: string, password: string) {
        if (username.length == 0) {
            this.showLoginTips(`账号不能为空`);
            return;
        } else if (this.containsWhitespace(username) || this.containsWhitespace(password)) {
            this.showLoginTips(`账号跟密码中不能包含空格`);
            return;
        } else if (password.length < 6) {
            this.showLoginTips(`密码的长度需要大于6`);
            return;
        }

        const loginData = { username, password };

        // 发起登录请求
        fetch(`${SQL_HOST}/api/login`, {  // 后端登录接口地址
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',  // 设置请求头为 JSON 格式
            },
            body: JSON.stringify(loginData),  // 将用户名和密码作为请求体
        })
            .then(response => response.json())  // 解析 JSON 响应
            .then(data => {
                if (data.message === '登录成功') {
                    // 登录成功，存储 JWT（可以用于后续认证）
                    // cc.sys.localStorage.setItem('auth_token', data.token);
                    // // 跳转到游戏主界面
                    this.UserName = username;
                    this.NeedLogin = false;
                    this.init();
                } else {
                    // cc.log('登录失败: ' + data.message);
                    console.error('登录失败: ' + data.message);
                    this.showLoginTips(`账号不存在`);
                    // 显示错误信息
                }
            })
            .catch(error => {
                // cc.log('请求失败: ' + error);
                console.error('请求失败: ' + error);
            });

    }

    /**注册 */
    register(username: string, password: string) {
        if (username.length == 0) {
            this.showRegisterTips(`账号不能为空`);
            return;
        } else if (password.length < 6 || password.length > 18) {
            this.showRegisterTips(`密码的长度需要6-18位`);
            return;
        } else if (this.containsWhitespace(username) || this.containsWhitespace(password)) {
            this.showRegisterTips(`账号跟密码中不能包含空格`);
            return;
        } else if (!this.isAlphanumeric(password)) {
            this.showRegisterTips(`密码只能是数字跟字母`);
            return;
        }

        const registerData = { username, password };

        // 发起注册请求
        fetch(`${SQL_HOST}/api/register`, {  // 后端注册接口地址
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',  // 设置请求头为 JSON 格式
            },
            body: JSON.stringify(registerData),  // 将用户名和密码作为请求体
        })
            .then(response => response.json())  // 解析 JSON 响应
            .then(data => {
                if (data.message === '注册成功') {
                    // cc.log('注册成功');
                    // console.log('注册成功');
                    this.showPanel(this._loginPanel);

                    // 跳转到登录界面
                    // cc.director.loadScene('LoginScene');
                } else {
                    // cc.log('注册失败: ' + data.message);
                    // 显示错误信息
                    console.error('注册失败: ' + data.message);
                    this.showRegisterTips(data.message);
                }
            })
            .catch(error => {
                // cc.log('请求失败: ' + error);
                console.error('请求失败: ' + error);
            });
    }

    /** 检查字符串是否只包含空格*/
    containsWhitespace(str: string): boolean {
        const regex = /\s/;  // \s 匹配任意空白字符（包括空格、制表符等）
        return regex.test(str);
    }

    /**查找用户数据 */
    async getDataByName(userName: string) {
        const data = { tableName, userName };

        try {
            const response = await fetch(`${SQL_HOST}/api/getData`, {  // 后端登录接口地址
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',  // 设置请求头为 JSON 格式
                },
                body: JSON.stringify(data),  // 将用户名和密码作为请求体
            });

            const result = await response.json();  // 解析 JSON 响应

            if (result.message === '查找成功') {
                // 将返回的数据存储在实例属性中
                this.Birthday = result.results[0].birthday;
                GameData.Cleared = result.results[0].cleared;
                GameData.Unlock = result.results[0].unlock;
                return { found: true, data: result.results };  // 返回一个包含结果的对象
            } else {
                // console.log(result.message);
                return { found: false, message: result.message };  // 返回一个包含失败信息的对象
            }

        } catch (e) {
            console.error('请求失败: ' + error);
            return { found: false, message: '请求失败' };  // 请求失败时返回错误信息
        }
    }

    /**添加用户数据 */
    addDataByName(userName: string, birthday: string, cleared: number[], unlock: number) {

        const data = { tableName, userName, birthday, cleared, unlock };

        fetch(`${SQL_HOST}/api/addData`, {  // 后端登录接口地址
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',  // 设置请求头为 JSON 格式
            },
            body: JSON.stringify(data),  // 将用户名和密码作为请求体
        })
            .then(response => response.json())  // 解析 JSON 响应
            .then(data => {
                if (data.message === '添加成功') {
                    console.log(data);
                } else {
                    // this.showLoginTips(data.message);
                    // 显示错误信息
                    console.log(data);
                }
            })
            .catch(error => {
                // cc.log('请求失败: ' + error);
                console.error('请求失败: ' + error);
            });
    }

    /**修改用户数据 */
    updateDataByName(userName: string = this.UserName, cleared: number[] = GameData.Cleared, unlock: number = GameData.Unlock) {

        const data = { tableName, userName, cleared, unlock };

        fetch(`${SQL_HOST}/api/updateData`, {  // 后端登录接口地址
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',  // 设置请求头为 JSON 格式
            },
            body: JSON.stringify(data),  // 将用户名和密码作为请求体
        })
            .then(response => response.json())  // 解析 JSON 响应
            .then(data => {
                if (data.message === '修改成功') {
                    console.log(data);
                } else {
                    // this.showLoginTips(data.message);
                    // 显示错误信息
                    console.log(data);
                }
            })
            .catch(error => {
                // cc.log('请求失败: ' + error);
                console.error('请求失败: ' + error);
            });
    }

    /**
     * 检查字符串是否只包含字母和数字
     * @param str 
     * @returns 
     */
    isAlphanumeric(str: string): boolean {
        const regex = /^[A-Za-z0-9]+$/;
        return regex.test(str);
    }

    /** 身份认证 */
    async verify(name: string, idCard: string): Promise<any> {
        // 参数校验（可抛出具体错误）
        if (!/^[\u4e00-\u9fa5]{2,10}$/.test(name)) {
            throw new Error(ERROR.名字错误);
        }
        if (!/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/.test(idCard)) {
            throw new Error(ERROR.身份证格式错误);
        }

        return new Promise((resolve, reject) => {
            // 1. 构建请求URL和参数
            //test1
            // const params = new URLSearchParams({
            //     name: name,
            //     idCard: idCard
            // });

            //test2 URLSearchParams对象会自动处理编码
            // const params = new URLSearchParams({
            //     name: name,
            //     idNo: idCard
            // });

            const data = `name=${encodeURIComponent(name)}&idcard=${encodeURIComponent(idCard)}`;
            // const data = `name=${name}&idcard=${idCard}`;

            // 构建请求参数
            const xhr = new XMLHttpRequest();
            // xhr.open(METHOD, `${HOST}${PATH}?${params}`);
            xhr.open(METHOD, `${HOST}${PATH}`, true);

            // 设置请求头
            xhr.setRequestHeader("Authorization", `APPCODE ${APPCODE}`);
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

            // 响应处理
            xhr.onload = () => {
                // console.log(xhr);

                if (xhr.status === 200) {
                    try {
                        const data = JSON.parse(xhr.responseText);
                        // console.log(data);
                        resolve(data); // 返回解析后的数据
                    } catch (e) {
                        reject(new Error(ERROR.响应数据解析失败));
                    }
                } else {
                    reject(new Error(`请求失败: ${xhr.statusText}`));
                }
            };

            // 错误处理
            xhr.onerror = () => reject(new Error(ERROR.网络请求异常));
            xhr.ontimeout = () => reject(new Error(ERROR.请求超时));

            // xhr.send();
            xhr.send(data);
        });
    }

    /** 开始认证 */
    async startRZ(name: string, id: string) {
        try {
            const result = await this.verify(name, id);
            if (result.code == 200) {
                //认证通过
                if (result.data.result == 0) {
                    //结果一致
                    this._authenticationPanel.active = false;

                    //不需要账号
                    // const data = {
                    //     birthday: result.data.birthday,
                    // } as _UserData;
                    // sys.localStorage.setItem(KEY_Authentication, JSON.stringify(data));

                    //初始化
                    this.addDataByName(this.UserName, result.data.birthday, [], 1);
                    this.init();
                } else if (result.data.result == 1) {
                    //结果不一致
                    this.againAuthentication(ERROR.结果不一致);
                }
            } else {
                // console.error("认证失败:", result.msg);
                this.againAuthentication(result.msg);
            }
        } catch (error) {
            // console.error("发生错误:", error.message);
            //错误处理
            this.againAuthentication(error.message);
        }
    }

    /** 认证失败*/
    againAuthentication(error: string) {
        this._isClick = true;
        if (error === ERROR.名字错误) {
            this.showTips(ERROR.名字错误)
        } else if (error === ERROR.身份证格式错误) {
            this.showTips(ERROR.身份证格式错误)
        } else {
            this.showTips(error + ",请重试!")
        }
    }

    /**获取当前时间  年月日*/
    getCurrentDateTime(): string {
        const now = new Date();

        // 补零函数（确保两位数字）
        const padZero = (num: number): string => {
            let str = num.toString();
            if (str.length == 1) str = "0" + str;
            return str;
        }

        return `${now.getFullYear()}-${padZero(now.getMonth() + 1)  // 月份从0开始
            }-${padZero(now.getDate())}`;
    }

    /**检查登录日期是否刷新 */
    checkRefesh(preTime: string): boolean {
        const preTimes = preTime.split("-");
        const curTimes = this.getCurrentDateTime().split("-");
        return !(preTimes[0] === curTimes[0] && preTimes[1] === curTimes[1] && preTimes[2] === curTimes[2]);
    }


    /**刷新未成年人游戏时间 */
    refeshTime() {
        if (!this.isAllowedTime()) {
            clearInterval(this._intervalId);
            this.showPanel(this._timeOverPanel);
        }
    }

    /**检查玩家的年龄 --不知道年龄*/
    checkAgeByBirthday(birthday: string): PLAYER {
        const _playerYear: string = birthday.slice(0, 4);
        const playerYear: number = Number(_playerYear);
        const curYear: number = new Date().getFullYear() - playerYear;

        const _playerMouth: string = birthday.slice(4, 6);
        const playerMouth: number = _playerMouth[0] === "0" ? Number(_playerMouth[1]) : Number(_playerMouth);
        const curMouth: number = new Date().getMonth() + 1;

        const _playerDate: string = birthday.slice(6);
        const playerDate: number = _playerDate[0] === "0" ? Number(_playerDate[1]) : Number(_playerDate);
        const curData: number = new Date().getDate();

        // console.log("Player:", playerMouth, playerDate, "  Cur:", curMouth, curData);

        const age = (playerMouth < curMouth || (playerMouth == curMouth && playerDate <= curData)) ? curYear : curYear - 1;

        if (age < 8) {
            //未满12岁
            return PLAYER.未满8周岁;
        } else if (age < 18) {
            //12-18岁
            return PLAYER.未成年;
        } else {
            //18岁以上
            return PLAYER.成年;
        }
    }

    /** 辅助函数，用于判断是否允许进入游戏的时间段 */
    isAllowedTime() {
        // 节假日判断
        const date = new Date();
        const yue = date.getMonth() + 1;
        const ri = date.getDate();
        const xq = date.getDay();
        const hour = date.getHours();

        if (
            // (yue == 1 && ri >= 21 && ri <= 27) || // 春节
            (yue == 4 && ri >= 4 && ri <= 6) || // 清明节
            (yue == 5 && ri >= 1 && ri <= 5) || // 劳动节
            ((yue == 5 && ri == 31) || (yue == 6 && ri >= 1 && ri <= 2)) || // 端午节
            (yue == 10 && ri >= 1 && ri <= 7)  // 国庆节
        ) {
            return hour >= 20 && hour < 21;
        }

        // 周末判断
        if (xq == 5 || xq == 6 || xq == 0) { // 周五、周六、周日
            return hour >= 20 && hour < 21;
        }

        // 平常日子不允许
        return false;
    }

    showTips(tips: string) {
        Tween.stopAllByTarget(this._tipsUIOpacity);
        this._tipsLabel.string = tips;
        this._tipsUIOpacity.opacity = 255;
        tween(this._tipsUIOpacity)
            .delay(2)
            .to(1, { opacity: 0 }, { easing: `sineOut` })
            .start();
    }

    showLoginTips(tips: string) {
        Tween.stopAllByTarget(this._loginTipsUIOpacity);
        this._loginTipsLabel.string = tips;
        this._loginTipsUIOpacity.opacity = 255;
        tween(this._loginTipsUIOpacity)
            .delay(2)
            .to(1, { opacity: 0 }, { easing: `sineOut` })
            .start();
    }

    showRegisterTips(tips: string) {
        Tween.stopAllByTarget(this._registerTipsUIOpacity);
        this._registerTipsLabel.string = tips;
        this._registerTipsUIOpacity.opacity = 255;
        tween(this._registerTipsUIOpacity)
            .delay(2)
            .to(1, { opacity: 0 }, { easing: `sineOut` })
            .start();
    }

}

